package com.means.polymerize.mainstay.terminal;

import cn.hutool.core.util.StrUtil;
import com.means.polymerize.common.constants.Global;
import com.means.polymerize.core.terminal.common.lang.SessionStorageContainer;
import com.means.polymerize.core.terminal.common.lang.WebSocketSessionSender;
import com.means.polymerize.core.terminal.service.TerminalService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

/**
 * 终端Web套接字回声
 * The type Terminal web socket echo.
 *
 * @author xuhiafeng
 * @date 2021.05.09
 */
@Component
public class TerminalWebSocketEcho {
    private static TerminalService service;

    /**
     * Instantiates a new Terminal web socket echo.
     *
     * @param service the service
     */
    @Autowired
    public void setService(TerminalService service) {
        TerminalWebSocketEcho.service = service;
    }

    /**
     * The type Terminal server.
     */
    @Slf4j
    @Service
    @SuppressWarnings({"unused", "DuplicatedCode"})
    @ServerEndpoint(value = "/echo/terminal/{token}/{timestamp}")
    public static class TerminalServer {
        /**
         * On open.
         *
         * @param session the session
         */
        @OnOpen
        @SneakyThrows
        public void onOpen(Session session) {
            /* 获取请求头 */
            final String token = session.getPathParameters().get(Global.TOKEN);
            /* 检查认证参数 */
            if (StrUtil.isEmpty(token)) {
                session.getAsyncRemote().sendText("认证失败!!");
                session.close();
                return;
            }
            log.debug(String.format("操作者：[%s][%s]，已接入系统", token, session.getId()));
            SessionStorageContainer.setSessions(token, new WebSocketSessionSender(session));
        }

        /**
         * On message.
         *
         * @param message the message
         * @param session the session
         */
        @OnMessage
        @SneakyThrows
        public void onMessage(String message, Session session) {
            /* 获取请求头 */
            final String token = session.getPathParameters().get(Global.TOKEN);
            /* 检查认证参数 */
            if (StrUtil.isEmpty(token)) {
                session.getAsyncRemote().sendText("认证失败!!");
                session.close();
                return;
            }
            log.debug(String.format("操作者：%s，发送信息：%s", token, message));
            service.reachEcho(token, message);
        }

        /**
         * On close.
         */
        @OnClose
        @SneakyThrows
        public void onClose(Session session) {
            final String token = session.getPathParameters().get(Global.SEC_WEBSOCKET_KEY);
            if (StrUtil.isNotEmpty(token)) {
                service.closeSessionConnection(token);
                log.info(String.format("操作者：%s，退出系统", token));
            }
        }

        /**
         * On error.
         *
         * @param session the session
         * @param e       the error
         */
        @OnError
        public void onError(Session session, Throwable e) {
            log.debug(String.format("用户:[%s],数据传输错误", session.getPathParameters().get(Global.TOKEN)));
            e.printStackTrace();
        }
    }
}
